#include "widget.h"
#include "ui_widget.h"

#include <QMessageBox>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    // 设置窗口标题
    this->setWindowTitle("服务端");
    // 1. 创建tcpServer实例
    tcpServer = new QTcpServer(this);
    // 2. 连接槽函数,处理请求
    connect(tcpServer, &QTcpServer::newConnection, this, &Widget::processConnection);
    // 3. 绑定并监听端口
    bool ret = tcpServer->listen(QHostAddress::Any, 9090);
    if(!ret) {
        QMessageBox::critical(this, "服务器启动失败", tcpServer->errorString());
        return;
    }
}

Widget::~Widget()
{
    delete ui;
}

void Widget::processConnection()
{
    // 1. 通过tcpServer拿到socket对象,用来和客户端通信
    QTcpSocket *clientSocket = tcpServer->nextPendingConnection();
    // 2. 获取客户端地址端口等信息,显示到界面
    QString log = "[" + clientSocket->peerAddress().toString() + ":" + QString::number(clientSocket->peerPort())
                  + "] 客户端上线";
    ui->listWidget->addItem(log);
    // 3. 通过信号槽,处理客户端发来的请求
    connect(clientSocket, &QTcpSocket::readyRead, this, [ = ]() {
        // a) 读取出请求数据
        QString request = clientSocket->readAll(); // 返回QByteArray,隐式转换成QString
        // b) 根据请求处理响应
        const QString& response = process(request);
        // c) 将响应写回客户端
        clientSocket->write(response.toUtf8());
        // d) 把上诉信息记录到日志,显示到界面查看
        QString log = "[" + clientSocket->peerAddress().toString() + ":" + QString::number(clientSocket->peerPort())
                      + "]" + "request: " + request + ", response: " + response;
        ui->listWidget->addItem(log);
    });
    // 4. 通过信号槽,处理客户端断开连接
    connect(clientSocket, &QTcpSocket::disconnected, this, [ = ]() {
        // a) 显示日志,断开连接
        QString log = "[" + clientSocket->peerAddress().toString() + ":" + QString::number(clientSocket->peerPort())
                      + "] 客户端下线";
        ui->listWidget->addItem(log);
        // b) 手动释放clientSocket
        clientSocket->deleteLater(); // 下一轮事件循环再释放,比delete更安全,保证槽函数逻辑全部执行完
    });
}

// 回显服务器处理
QString Widget::process(const QString &request)
{
    return request;
}
